package org.wiztools.paginationlib;

import java.util.Collection;

/**
 * Utility class to extract a page---a subset of the given collection.
 * @author subwiz
 */
public final class PaginationUtil {
    
    private PaginationUtil() {} // Don't allow creation of instance!

    /**
     * Convenience method to get a page with all content from Collection.
     * @param <T> The type of the collection.
     * @param data The collection data.
     * @return Contents of the requested page encapsulated in PaginatedItems.
     * @see org.wiztools.paginationlib.PaginatedItems
     */
    public static <T> PaginatedItems<T> getAllPaginatedItems(final Collection<T> data) {
        return getPaginatedItems(data, data.size(), 1);
    }
    
    /**
     * Convenience method to get a particular page content from Collection.
     * @param <T> The type of the collection.
     * @param data The collection to be paginated.
     * @param pageSize How many contents to return in a page. Minimum value is 1.
     * @param page The page content to serve. Page number starts with 1.
     * @return Contents of the requested page encapsulated in PaginatedItems.
     * @see org.wiztools.paginationlib.PaginatedItems
     */
    public static <T> PaginatedItems<T> getPaginatedItems(final Collection<T> data,
            final int pageSize, final int page) {
        return getPaginatedItems(data, pageSize, page, new PaginatedItemsImpl<T>(pageSize));
    }

    /**
     * Convenience method to get a particular page content from Collection.
     * @param <T> The type of the collection.
     * @param data The collection to be paginated.
     * @param pageSize How many contents to return in a page. Minimum value is 1.
     * @param page The page content to serve. Page number starts with 1.
     * @param out If you want to return a custom implementation of PaginatedItems, use this.
     * @return Contents of the requested page encapsulated in PaginatedItems.
     * @see org.wiztools.paginationlib.PaginatedItems
     * @see org.wiztools.paginationlib.PaginatedItemsSetters
     */
    public static <T> PaginatedItems<T> getPaginatedItems(final Collection<T> data,
            final int pageSize, final int page, final PaginatedItemsSetters<T> out) {
        // Validation:
        if(pageSize < 1) throw new IllegalArgumentException("Page-size cannot be less than 1");
        if(page < 1) throw new IllegalArgumentException("Page cannot be less than 1");

        // Create the page:
        out.setPageSize(pageSize);
        out.setPage(page);
        
        if (data != null)
            out.setTotalCount(data.size());
        else
            out.setTotalCount(0);

        if (data != null) {
            final int totalNumberOfPages = (data.size() / pageSize) + (data.size() % pageSize==0?0 : 1);
            out.setNumberOfPages(totalNumberOfPages);
        }
        else
        	out.setNumberOfPages(0);

        if(out.getNumberOfPages() < page) {
            return out;
        }

        final int startIndex = pageSize * (page -1);
        int i = 0;
        int j = 0;
        for(T t: data) {
            if(i == startIndex) {
                out.addPaginatedItem(t);
                j++;
            }
            else if(j > 0 && j < pageSize) {
                out.addPaginatedItem(t);
                j++;
            }
            i++;
        }
        
        return out;
    }
}
